package blue.mic.server;
import java.awt.AWTException;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

import javax.bluetooth.RemoteDevice;
import javax.microedition.io.StreamConnection;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
 
public class RecvServerThread extends Thread {	
	private StreamConnection conn; // client connection
	private InputStream in;
	private OutputStream out;
	private volatile boolean isRunning = false;
	private String clientName;
	AudioInputStream audioInputStream;
	static AudioInputStream ais;
	static AudioFormat format;
	static boolean status = true;
	static int sampleRate = 48000;

	static DataLine.Info dataLineInfo;
	static SourceDataLine sourceDataLine;
	
	public RecvServerThread(StreamConnection conn) {
		this.conn = conn;
		// store the name of the connected client
		clientName = reportDeviceName(conn);
		System.out.println("  Handler spawned for client: " + clientName);
	} // end of ThreadedEchoHandler()
 
	private String reportDeviceName(StreamConnection conn) {
	/* Return the 'friendly' name of the device being examined,
 	or "device ??" */
		String devName;
		try {
			RemoteDevice rd = RemoteDevice.getRemoteDevice(conn);
			devName = rd.getFriendlyName(false);  // to reduce connections
		} catch (IOException e) { devName = "device ??";  }
		return devName;
	}  // end of reportDeviceName()
 
	public void run() {
		/* Get an InputStream and OutputStream from the stream connection,
  		and start processing client messages. */
		try {
			// Get I/O streams from the stream connection
			in = conn.openInputStream();
			out = conn.openOutputStream();
			processMsgs();
			System.out.println("  Closing " + clientName + " connection");
			if (conn != null) {
				in.close();
				out.close();
				conn.close();
			}
		} catch (IOException e) {  
			System.out.println(e);  
		} catch (AWTException e) {
			e.printStackTrace();
		}
	}  // end of run()
 
	private void processMsgs() throws AWTException, NumberFormatException, IOException {
		isRunning = true;
		String line=null;
	    byte[] receiveData = new byte[9728];
	   
	    format = new AudioFormat(sampleRate, 16, 2, true, false);
	  
	    dataLineInfo = new DataLine.Info(SourceDataLine.class, format);
	    try {
			sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
		    sourceDataLine.open(format);
		    sourceDataLine.start();
		} catch (LineUnavailableException e) {
			e.printStackTrace();
		}


	    FloatControl volumeControl = (FloatControl) sourceDataLine.getControl(FloatControl.Type.MASTER_GAIN);
	    volumeControl.setValue(5.00f);

	    // if received data type is byte
	    DatagramPacket receivePacket = new DatagramPacket(receiveData,
	            receiveData.length);
	    ByteArrayInputStream baiss = new ByteArrayInputStream(
	            receivePacket.getData());
	    
/*	    while (status == true) {
	    	DatagramSocket serverSocket = new DatagramSocket(port);
	        serverSocket.receive(receivePacket);
	        ais = new AudioInputStream(baiss, format, receivePacket.getLength());
	        toSpeaker(receivePacket.getData());
	    }
	    sourceDataLine.drain();
	    sourceDataLine.close();
	    */
		
		// String while
		while (isRunning) {
			if((line = readData()) == null)
				isRunning = false;
			else {
				System.out.println(line);
				byte[] byteline = line.getBytes();
		        receivePacket.setData(byteline);
		        ais = new AudioInputStream(baiss, format, receivePacket.getLength());
		        toSpeaker(receivePacket.getData());				
			}
		}
	    sourceDataLine.drain();
	    sourceDataLine.close();		
     } // end of processMsgs()
 
 
	public void closeDown() { 
		isRunning = false;  }

	
	// string readData method
	private String readData() throws IOException {
		BufferedReader bReader = new BufferedReader(new InputStreamReader(in));         
		String data = bReader.readLine();
 
		return data;
	}   // end of readData()
	
	public static void toSpeaker(byte soundbytes[]) {
	    try {
	        sourceDataLine.write(soundbytes, 0, soundbytes.length);
	    } catch (Exception e) {
	        System.out.println("Not working in speakers...");
	        e.printStackTrace();
	    }
	}
	
	private boolean sendMessage(String msg) { // the message format is "<length> msg" in byte form
		try {
			out.write(msg.length());
			out.write(msg.getBytes());
			out.flush(); 
			return true;
		} catch (Exception e) {  
			System.out.println(clientName + " sendMessage(): " + e);  
			return false;
			} 
	}  // end of sendMessage()
 }  // end of RecvServerThread class 
